using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.DirectX;
using TgcViewer.Example;
using TgcViewer;
using Microsoft.DirectX.Direct3D;
using System.Drawing;
using TgcViewer.Utils.TgcGeometry;
using TgcViewer.Utils;

namespace AlumnoEjemplos.TP3D.Collider
{
    public class CollisionBox : CollisionSurface
    {
        protected List<Vector3> _vertexes;

        protected Vector3 _maxVertex = new Vector3();
        protected Vector3 _minVertex = new Vector3();
        protected bool _isDirty = true;

        public override void Render()
        {
            Device d3dDevice = GuiController.Instance.D3dDevice;

            CustomVertex.PositionColored[] data = new CustomVertex.PositionColored[24];
            int color = Color.Yellow.ToArgb();
            int index = 0;

            //Cuadrado de atras
            data[index++] = new CustomVertex.PositionColored(MinVertex.X, MinVertex.Y, MinVertex.Z, color);
            data[index++] = new CustomVertex.PositionColored(MaxVertex.X, MinVertex.Y, MinVertex.Z, color);

            data[index++] = new CustomVertex.PositionColored(MinVertex.X, MinVertex.Y, MinVertex.Z, color);
            data[index++] = new CustomVertex.PositionColored(MinVertex.X, MaxVertex.Y, MinVertex.Z, color);

            data[index++] = new CustomVertex.PositionColored(MinVertex.X, MaxVertex.Y, MinVertex.Z, color);
            data[index++] = new CustomVertex.PositionColored(MaxVertex.X, MaxVertex.Y, MinVertex.Z, color);

            data[index++] = new CustomVertex.PositionColored(MaxVertex.X, MinVertex.Y, MinVertex.Z, color);
            data[index++] = new CustomVertex.PositionColored(MaxVertex.X, MaxVertex.Y, MinVertex.Z, color);


            //Cuadrado de adelante
            data[index++] = new CustomVertex.PositionColored(MinVertex.X, MinVertex.Y, MaxVertex.Z, color);
            data[index++] = new CustomVertex.PositionColored(MaxVertex.X, MinVertex.Y, MaxVertex.Z, color);

            data[index++] = new CustomVertex.PositionColored(MinVertex.X, MinVertex.Y, MaxVertex.Z, color);
            data[index++] = new CustomVertex.PositionColored(MinVertex.X, MaxVertex.Y, MaxVertex.Z, color);

            data[index++] = new CustomVertex.PositionColored(MinVertex.X, MaxVertex.Y, MaxVertex.Z, color);
            data[index++] = new CustomVertex.PositionColored(MaxVertex.X, MaxVertex.Y, MaxVertex.Z, color);

            data[index++] = new CustomVertex.PositionColored(MaxVertex.X, MinVertex.Y, MaxVertex.Z, color);
            data[index++] = new CustomVertex.PositionColored(MaxVertex.X, MaxVertex.Y, MaxVertex.Z, color);


            //Union de ambos cuadrados
            data[index++] = new CustomVertex.PositionColored(MinVertex.X, MinVertex.Y, MinVertex.Z, color);
            data[index++] = new CustomVertex.PositionColored(MinVertex.X, MinVertex.Y, MaxVertex.Z, color);

            data[index++] = new CustomVertex.PositionColored(MaxVertex.X, MinVertex.Y, MinVertex.Z, color);
            data[index++] = new CustomVertex.PositionColored(MaxVertex.X, MinVertex.Y, MaxVertex.Z, color);

            data[index++] = new CustomVertex.PositionColored(MinVertex.X, MaxVertex.Y, MinVertex.Z, color);
            data[index++] = new CustomVertex.PositionColored(MinVertex.X, MaxVertex.Y, MaxVertex.Z, color);

            data[index++] = new CustomVertex.PositionColored(MaxVertex.X, MaxVertex.Y, MinVertex.Z, color);
            data[index++] = new CustomVertex.PositionColored(MaxVertex.X, MaxVertex.Y, MaxVertex.Z, color);


            d3dDevice.SetTexture(0, null);
            d3dDevice.SetTexture(1, null);
            d3dDevice.Material = TgcD3dDevice.DEFAULT_MATERIAL;
            d3dDevice.Transform.World = Matrix.Identity;

            d3dDevice.VertexFormat = CustomVertex.PositionColored.Format;
            d3dDevice.DrawUserPrimitives(PrimitiveType.LineList, data.Length / 2, data);
        }
        public CollisionBox(Placeable placeable)
            : base(placeable)
        {
        }

        #region Accesors
        public virtual List<Vector3> Vertexes
        {
            set
            {
                this._vertexes = value;
            }
            get
            {
                this._vertexes = new List<Vector3>();
                this._vertexes.Add(this.MaxVertex);
                this._vertexes.Add(new Vector3(this.MaxVertex.X, this.MaxVertex.Y, this.MinVertex.Z));
                this._vertexes.Add(new Vector3(this.MaxVertex.X, this.MinVertex.Y, this.MaxVertex.Z));
                this._vertexes.Add(new Vector3(this.MaxVertex.X, this.MinVertex.Y, this.MinVertex.Z));
                this._vertexes.Add(new Vector3(this.MinVertex.X, this.MaxVertex.Y, this.MaxVertex.Z));
                this._vertexes.Add(new Vector3(this.MinVertex.X, this.MaxVertex.Y, this.MinVertex.Z));
                this._vertexes.Add(new Vector3(this.MinVertex.X, this.MinVertex.Y, this.MaxVertex.Z));
                this._vertexes.Add(this.MinVertex);
                this._isDirty = false;
                return this._vertexes;
            }
        }


        public virtual Vector3 MinVertex
        {
            set
            {
                this._minVertex = value;
                this._isDirty = true;
            }
            get
            {
                return this._minVertex;
            }
        }
        public virtual Vector3 MaxVertex
        {
            set
            {
                this._maxVertex = value;
                this._isDirty = true;
            }
            get
            {
                return this._maxVertex;
            }
        }

        #endregion

        #region Intersections logic
        public override bool Collides(CollisionSurface surface)
        {
            if (surface == this) return false;
            return surface.IntersectWithBox(this);
        }


        public bool laTenesAdentro(CollisionBox box)
        {
            //SI PASMAN, VOS TAMBIEN LA TENES ADENTRO

            if ((this.MinVertex.X <= box.MinVertex.X) &&
                   (this.MinVertex.Y <= box.MinVertex.Y) &&
                   (this.MinVertex.Z <= box.MinVertex.Z) &&
                   (this.MaxVertex.X >= box.MaxVertex.X) &&
                   (this.MaxVertex.Y >= box.MaxVertex.Y) &&
                   (this.MaxVertex.Z >= box.MaxVertex.Z))
            {
                return true;
            }
            return false;
        }
        public bool laTenesEncerrada(CollisionBox box)
        {
            return this.IntersectWithBox(box) && !this.laTenesAdentro(box) &&
                     (this.MinVertex.X > box.MinVertex.X) &&
                     (this.MinVertex.Y > box.MinVertex.Y) &&
                     (this.MinVertex.Z > box.MinVertex.Z) &&
                     (this.MaxVertex.X < box.MaxVertex.X) &&
                     (this.MaxVertex.Y < box.MaxVertex.Y) &&
                     (this.MaxVertex.Z < box.MaxVertex.Z);
        }
        public bool laTenesAtravesada(CollisionBox box)
        {
            return this.IntersectWithBox(box) && !this.laTenesAdentro(box) && !this.laTenesEncerrada(box);
        }

        public override bool IntersectWithBox(CollisionBox box)
        {
            if (((this.MinVertex.X <= box.MinVertex.X && this.MaxVertex.X >= box.MaxVertex.X) ||
                            (this.MinVertex.X >= box.MinVertex.X && this.MinVertex.X <= box.MaxVertex.X) ||
                            (this.MaxVertex.X >= box.MinVertex.X && this.MaxVertex.X <= box.MaxVertex.X)) &&
                           ((this.MinVertex.Y <= box.MinVertex.Y && this.MaxVertex.Y >= box.MaxVertex.Y) ||
                            (this.MinVertex.Y >= box.MinVertex.Y && this.MinVertex.Y <= box.MaxVertex.Y) ||
                            (this.MaxVertex.Y >= box.MinVertex.Y && this.MaxVertex.Y <= box.MaxVertex.Y)) &&
                           ((this.MinVertex.Z <= box.MinVertex.Z && this.MaxVertex.Z >= box.MaxVertex.Z) ||
                            (this.MinVertex.Z >= box.MinVertex.Z && this.MinVertex.Z <= box.MaxVertex.Z) ||
                            (this.MaxVertex.Z >= box.MinVertex.Z && this.MaxVertex.Z <= box.MaxVertex.Z)))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public override bool IntersectWithSphere(CollisionSphere sphere)
        {
            return sphere.IntersectWithBox(this);
        }
        #endregion
    }
}
